home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / HYPERCAR / POPUPMEN / POPUP.C
C/C++ Source or Header  |  1991-01-18  |  7KB  |  302 lines

  1. /*        PopUpMenu 2.0b4
  2.  
  3.         This HyperCard external function presents the user with a pop-up-
  4.         menu from which she would then select an item.  If no item is 
  5.         selected NULL is returned to your HyperTalk script.  Otherwise, 
  6.         the ordinal number of the item selected is returned.
  7.         
  8.         PopUpMenu is called with one to four arguments.  The first argument 
  9.         is the menu.  This menu is a series of menu items.  Each item is 
  10.         separated by either a comma, semi-colon, carriage-return, line-
  11.         feed, or tab.  Each item's characters will be added to the menu 
  12.         with AppendMenu;  Thus, any of the AppendMenu meta-characters can 
  13.         be used (except for the hierarchical menu meta-character). 
  14.         
  15.         The second argument is the number of an item to be checked.  If 
  16.         this argument is missing or empty then no item will be checked.
  17.         
  18.         The third and fourth arguments position the pop-up-menu.  The
  19.         coordinates must be global to the screen.  (I have retained 
  20.         global coordinates to maintain compatibility with PopUpMenu 
  21.         1.x.)  If either of these arguments is missing or empty then
  22.         the menu position defaults to the current mouse position.
  23.         
  24.         If all arguments are omitted then version and copyright
  25.         information is returned.
  26.         
  27.         Usage example.
  28.         
  29.             on mouseDown
  30.                 get PopUpMenu( "Color,Mono,Psychedelic", 3 );
  31.                 
  32.                 if it is empty then
  33.                     answer "Nothing was selected."
  34.                 else
  35.                     answer item it of "Color,Mono,Psychedelic" && "was selected."
  36.                 end if
  37.             end mouseDown
  38.             
  39.         Good luck with your stacks!
  40.         
  41.         
  42.         Andrew Gilmartin
  43.         Computing & Information Services
  44.         Box 1885
  45.         Brown University
  46.         Providence, Rhode Island 02912
  47.         
  48.         andrew@brownvm.brown.edu (internet)
  49.         andrew@brownvm (bitnet)
  50.  
  51.         Neither I nor Brown University place any restrictions on the use of 
  52.         the external HyperTalk function PopUpMenu. I only request that you 
  53.         credit myself and Brown University; For example,
  54.         
  55.             PopUpMenu by Andrew Gilmartin, Brown University
  56.             
  57.         PopUpMenu has been tested with HyperCard 1.x and HyperCard 2.0. However, 
  58.         the developers have no desire or ability to support this product, and 
  59.         therefore PopUpMenu is delivered ╥as is╙ with no expressed or implied 
  60.         guarantees of operability or support.
  61.  
  62. */
  63.  
  64.  
  65.  
  66.  
  67.  
  68. #include "MenuMgr.h"
  69. #include "HyperXCmd.h"
  70. #include "utilities.h"
  71.  
  72.  
  73.  
  74.  
  75.  
  76. #define NULL  0L
  77.  
  78.  
  79. #define FALSE 0
  80. #define TRUE  1
  81.  
  82.  
  83. #define loop  for(;;)
  84.  
  85.  
  86.  
  87. #define MENU_ID 1024
  88. int gMenuID;
  89.  
  90.  
  91.  
  92. int unusedMenuID( int menuID );
  93.  
  94. int unusedMenuID( int menuID )
  95. {
  96.     while ( GetMHandle( menuID++ ) );
  97.     
  98.     return( menuID - 1 );
  99.     
  100. } /* unusedMenuID */
  101.  
  102.  
  103.  
  104.  
  105. MenuHandle popupmenu_create_menu( char * menu_items );
  106.  
  107. MenuHandle popupmenu_create_menu( menu_items )
  108.     char * menu_items;
  109. {
  110.     MenuHandle the_menu;
  111.     char       c;
  112.     struct
  113.     {
  114.         Str255 content;
  115.         char * pointer; /* where the next character should be placed in .content */
  116.         int    length;
  117.     } menu_item;
  118.     
  119.     
  120.     gMenuID = unusedMenuID( MENU_ID );
  121.     
  122.     if ( ( the_menu = NewMenu( gMenuID, "\p" ) ) != NULL ) 
  123.     {
  124.         menu_item.pointer = (char *) &menu_item.content;
  125.         menu_item.length  = 0;
  126.             
  127.         loop
  128.         {
  129.             switch ( c = *menu_items++ )
  130.             {
  131.                 case  ',':    /* I figure that these cases should cover most */
  132.                 case  ';':  /* uses of PopUpMenu...                        */
  133.                 case '\n':
  134.                 case '\r':
  135.                 case '\t':
  136.                     if ( menu_item.length > 0 )
  137.                     {
  138.                         *menu_item.pointer = '\0'; /* C strings end in a null! */ 
  139.                         CtoPstr( (char *) &menu_item.content );
  140.                         AppendMenu( the_menu, &menu_item.content );
  141.                     }
  142.                     
  143.                     menu_item.pointer = (char *) &menu_item.content;
  144.                     menu_item.length  = 0;
  145.                     break;
  146.                 
  147.                 case '\0':
  148.                     if ( menu_item.length > 0 )
  149.                     {
  150.                         *menu_item.pointer = '\0'; /* C strings end in a null! */
  151.                         CtoPstr( (char *) &menu_item.content );
  152.                         AppendMenu( the_menu, &menu_item.content );
  153.                     }
  154.                     goto outside_loop;
  155.                     
  156.                 default:
  157.                     if ( menu_item.length < ( sizeof( menu_item.content ) - 1 ) )
  158.                         *menu_item.pointer++ = c,
  159.                         menu_item.length++;
  160.             }
  161.             
  162.         }
  163.         outside_loop:;
  164.     }
  165.     
  166.     return the_menu;
  167.     
  168. } /* popupmenu_create_menu */
  169.  
  170.  
  171.  
  172.  
  173.  
  174. int popupmenu( char * menu_items, int checked_item, Point mouse_location );
  175.  
  176. int popupmenu( menu_items, checked_item, mouse_location )
  177.     char * menu_items;
  178.     int checked_item;
  179.     Point mouse_location;
  180. {
  181.     MenuHandle the_menu;
  182.     long       the_selected_item = 0;
  183.     int        the_checked_item;
  184.     
  185.     
  186.     /* Create Menu */
  187.     
  188.     the_menu = popupmenu_create_menu( menu_items );
  189.     if ( the_menu == NULL )
  190.         return 0;
  191.     
  192.     
  193.     /* Check Menu Item */
  194.     
  195.     if ( checked_item > 0 && checked_item <= CountMItems( the_menu ) )
  196.     {
  197.         CheckItem( the_menu, checked_item, TRUE );
  198.         the_checked_item = checked_item;
  199.     }
  200.     else
  201.     {
  202.         the_checked_item = 1;
  203.     }
  204.     
  205.     
  206.     /* Add the menu to the system */
  207.     
  208.     InsertMenu( the_menu, -1 );
  209.     
  210.     
  211.     /* Get Menu Selection */
  212.  
  213.     the_selected_item = PopUpMenuSelect( 
  214.         the_menu, 
  215.         mouse_location.v,
  216.         mouse_location.h,
  217.         the_checked_item );
  218.  
  219.  
  220.     /* Remove the menu from the system */
  221.     
  222.     DeleteMenu( gMenuID );
  223.     DisposeMenu( the_menu );
  224.     
  225.     
  226.     /* Return user's selection */
  227.     
  228.     return (int) ( the_selected_item & 0x0000FFFF );
  229.         
  230. } /* popupmenu */
  231.  
  232.  
  233.  
  234.  
  235.  
  236. pascal void main( XCmdBlockPtr paramPtr );
  237.  
  238. pascal void main( paramPtr )
  239.     XCmdBlockPtr paramPtr;
  240. {
  241.     char * menu_items /* = NULL */;
  242.     int    checked_item = -1;
  243.     int    selected_item /* = 0 */;
  244.     Point  mouse_location;
  245.     int    _mouse_location;
  246.     
  247.     XCMDSetupA4();
  248.  
  249.     /*    Get Mouse Location
  250.     
  251.         We need to get the mouse location early in the external just in case the 
  252.         user mouses ahead.  It would be better if the location of the last mouse 
  253.         down were available at the toolbox level...
  254.     */
  255.     
  256.     GetMouse( &mouse_location );
  257.     LocalToGlobal( &mouse_location );
  258.     
  259.     
  260.     /*    Parse Paramater List */
  261.     
  262.     switch ( paramPtr->paramCount )
  263.     {
  264.         case 4:
  265.             _mouse_location = param_to_integer( paramPtr->params[3] );
  266.             if ( _mouse_location > 0 )
  267.                 mouse_location.v = _mouse_location;
  268.             
  269.         case 3:
  270.             _mouse_location = param_to_integer( paramPtr->params[2] );
  271.             if ( _mouse_location > 0 )
  272.                 mouse_location.h = _mouse_location;
  273.                         
  274.         case 2:
  275.             checked_item = param_to_integer( paramPtr->params[1] );
  276.             
  277.         case 1:
  278.             MoveHHi( paramPtr->params[0] );
  279.             HLock( paramPtr->params[0] );
  280.             menu_items = *(paramPtr->params[0]);
  281.             
  282.             selected_item = popupmenu( menu_items, checked_item, mouse_location );
  283.             if ( selected_item != 0 )
  284.                 paramPtr->returnValue = integer_to_param( selected_item );
  285.                 
  286.             HUnlock( paramPtr->params[0] ); 
  287.             break;
  288.             
  289.         case 0:
  290.             paramPtr->returnValue = string_to_param( 
  291.                 "PopUpMenu 2.0b4 by Andrew Gilmartin, Brown University" );
  292.             break;
  293.             
  294.         default:
  295.             break;
  296.     }
  297.     
  298.     XCMDRestoreA4();
  299.  
  300.     /* Bye, Bye! */
  301.     
  302. } /* main */